<?php

    /**
     * Config
     *
     * This is the compiler of module's configuration: it merges two INI file in a single array and stores it in a temporary file
     *
     * @package      Core
     * @subpackage   Module_Config
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    final class Core_Module_Config extends Zend_Config
    {

	////////////////////////////////////////////////////////////////////////////
	//                                Variables                               //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Singleton instance
         *
         * Marked only as protected to allow extension of the class.
         * To extend, simply override {@link getInstance()}.
         *
         * @var Core_Plugin_Config
         */
        protected static $_instance = null;

		/**
		 * Zend_Registry object
		 *
		 * @var Zend_Registry
		 */
		protected $_registry = null;

	////////////////////////////////////////////////////////////////////////////
	//                             Static Methods                             //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Singleton instance
         *
		 * @param		string          $filename : the name of the configuration file
		 * @param		string|null     $section
		 * @param		boolean|array	$config
         *
         * @return      Core_Plugin_Config
         */
        public static function getInstance($filename, $section = null, $config = array('allowModifications' => true))
        {
            if (self::$_instance === null) {
                self::$_instance = new self($filename, $section, $config);
            }

            return self::$_instance;
        }

    ////////////////////////////////////////////////////////////////////////////
    //                                 Methods                                //
    ////////////////////////////////////////////////////////////////////////////

		/**
		 * Loads the section $section from the plugin config file for
		 * access facilitated by nested object properties.
		 *
		 * @param		string          $filename : the name of the configuration file
		 * @param		string|null     $section
		 * @param		boolean|array	$config
		 * @throws		Core_ArgumentNullException
		 * @throws		Core_IO_FileNotFoundException
		 *
		 * @see			Zend_Config_Ini
		 */
		public function __construct($filename, $section = null, $config = array('allowModifications' => true))
		{
            if ($filename === null) {
				throw new Core_ArgumentNullException('filename is a null reference');
			}

            if (strlen(trim($filename)) == 0) {
				throw new Core_ArgumentException('filename is a zero-length string');
			}

            $this->_registry = Zend_Registry::getInstance();
			$configs		 = $this->_get($filename, $section, $config);

            parent::__construct($configs, true);
		}

		/**
		 * Destructor
		 */
		public function __destruct()
		{
			unset($this);
		}

	////////////////////////////////////////////////////////////////////////////
	//                             Private Methods                            //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Reads and merges all the plugins configuration file
         * It stores the result in a temporary file
         *
         * @param		string          $filename : the name of the configuration file
		 * @param		string|null     $section
		 * @param		boolean|array	$config
		 * @throws		Core_ArgumentException
		 * @throws		Core_ArgumentNullException
		 * @throws		Core_IO_FileNotFoundException
         * @return      array			an object which contains configuration values
         */
        private function _get($filename, $section = null, $config = array('allowModifications' => true))
        {
            if ($filename === null) {
				throw new Core_ArgumentNullException('filename is a null reference');
			}

            if (strlen(trim($filename)) == 0) {
				throw new Core_ArgumentException('filename is a zero-length string');
			}

            $compile        = false;
			$configs        = array();
			$cachefile	    = Core_IO_Path::combine(PROJECT_TEMP_PATH, 'compiled', '~modules~');

            foreach ($this->_registry['modules'] as $name => $path) {
				$file = Core_IO_Path::combine($path, $filename);

				if (Core_IO_File::exists($file)) {
					if (@filemtime($file) > @filemtime($cachefile)) {
						$compile = true;
						break;
					}
				}
            }

            if ($compile) {
                foreach ($this->_registry['modules'] as $name => $path) {
                    $file = Core_IO_Path::combine($path, $filename);

                    if (Core_IO_File::exists($file)) {
                        $configurations = new Zend_Config_Ini($file, $section, $config);
                        $configs[strtolower($name)] = $configurations->toArray();
                    }
                }

                Core_IO_File::writeAll($cachefile, var_export($configs, true));
            } else {
                $str = Core_IO_File::readAll($cachefile);
                $configs = eval('return '. $str .';');
            }

            return $configs;
        }
    }
